﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace 多线程
{
    //线程同步lock,Monitor,Mutex,同步事件和等待句柄（中） 
    public partial class DuoXianChengTongBu : Form
    {
        public DuoXianChengTongBu()
        {
            InitializeComponent();
        }

        private void TestFunc(string str)
        {
            string readstr = string.Format("{0} {1}", str, System.DateTime.Now.Millisecond.ToString());
            listBox1.Items.Add(readstr);
            //Thread.Sleep(50);
        }

        #region 普通的
        private void btnStart_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            Thread thread1 = new Thread(new ThreadStart(thread1Func));
            Thread thread2 = new Thread(new ThreadStart(thread2Func));
            thread1.Start();
            thread2.Start();
        }


        private void thread1Func()
        {
            for (int count = 0; count < 10; count++)
            {
                TestFunc("Thread1 have run " + count.ToString() + " times");
                Thread.Sleep(30);
            }
        }

        private void thread2Func()
        {
            for (int count = 0; count < 10; count++)
            {
                TestFunc("Thread2 have run " + count.ToString() + " times");
                Thread.Sleep(100);
            }
        }
        #endregion
        #region Monitor
        private void btnMonitor_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            Thread thread1 = new Thread(new ThreadStart(thread1Monitor));
            Thread thread2 = new Thread(new ThreadStart(thread2Monitor));
            thread1.Start();
            thread2.Start();
        }


        private void thread1Monitor()
        {
            if (!Monitor.TryEnter(listBox1))
            {
                //TestFunc("Thread1 Can't visit Object " + listBox1.Name);
                return;
            }
            try
            {
                Monitor.Enter(listBox1);
                for (int count = 0; count < 10; count++)
                {
                    listBox1.Items.Add("Thread1 have run " + count.ToString() + " times");
                    //Thread.Sleep(30);
                }
            }
            finally
            {
                Monitor.Exit(listBox1);
            }
        }

        private void thread2Monitor()
        {
            if (!Monitor.TryEnter(listBox1))
            {
                //TestFunc("Thread2 Can't visit Object " + listBox1.Name);
                return;
            }
            try
            {
                Monitor.Enter(listBox1);
                for (int count = 0; count < 10; count++)
                {
                    listBox1.Items.Add("Thread2 have run " + count.ToString() + " times");
                    //Thread.Sleep(100);
                }
            }
            finally
            {
                Monitor.Exit(listBox1);
            }
        }




        #endregion
        #region Lock：定义在主动调用对象上
        private void btnLock_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            Thread thread1 = new Thread(new ThreadStart(thread1Lock));
            Thread thread2 = new Thread(new ThreadStart(thread2Lock));
            thread1.Start();
            thread2.Start();
        }

        private void thread1Lock()
        {
            lock (listBox1)
            {
                for (int count = 0; count < 10; count++)
                {
                    TestFunc("Thread1 have run " + count.ToString() + " times");
                    Thread.Sleep(30);
                }
            }
        }

        private void thread2Lock()
        {
            lock (listBox1)
            {
                for (int count = 0; count < 10; count++)
                {
                    TestFunc("Thread2 have run " + count.ToString() + " times");
                    Thread.Sleep(100);
                }
            }
        }
        #endregion
        #region Mutex:定义在被动调用对象上
        private void btnMutex_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            Thread thread1 = new Thread(new ThreadStart(thread1Mutex));
            Thread thread2 = new Thread(new ThreadStart(thread2Mutex));
            thread1.Start();
            thread2.Start();
        }

        private void btnMutex2_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            Thread thread1 = new Thread(new ThreadStart(thread1Mutex_2));
            Thread thread2 = new Thread(new ThreadStart(thread2Mutex_2));
            thread1.Start();
            thread2.Start();
        }

        private void btnMutex3_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            Thread thread1 = new Thread(new ThreadStart(thread1Mutex_3));
            Thread thread2 = new Thread(new ThreadStart(thread2Mutex_3));
            thread1.Start();
            thread2.Start();
        }

        private void thread1Mutex()
        {
            Counter.Add(listBox1,"1");
        }

        private void thread2Mutex()
        {
            Counter.Add(listBox1,"2");
        }

        Mutex mutex = new Mutex();
        private void thread1Mutex_2()
        {
            mutex.WaitOne();
            for (int count = 0; count < 10; count++)
            {
                TestFunc("Thread1 have run " + count.ToString() + " times");
                Thread.Sleep(30);
            }
            mutex.ReleaseMutex();
        }

        private void thread2Mutex_2()
        {
            mutex.WaitOne();
            for (int count = 0; count < 10; count++)
            {
                TestFunc("Thread2 have run " + count.ToString() + " times");
                Thread.Sleep(100);
            }
            mutex.ReleaseMutex();
        }

        private void thread1Mutex_3()
        {
            for (int count = 0; count < 10; count++)
            {
                lock (this)
                {
                    //mutex.WaitOne();
                    TestFunc("Thread1 have run " + count.ToString() + " times");
                    Thread.Sleep(30);
                    //mutex.ReleaseMutex();
                }
            }
        }

        private void thread2Mutex_3()
        {
            for (int count = 0; count < 10; count++)
            {
                lock (this)
                {
                    //mutex.WaitOne();
                    TestFunc("Thread2 have run " + count.ToString() + " times");
                    Thread.Sleep(30);
                    //mutex.ReleaseMutex();
                }
            }
        }
        #endregion
    }




    public static class Counter
    {
        static int counum = 0;
        static Mutex mu = new Mutex();
        public static void Add(ListBox box,string str)
        {
            mu.WaitOne();
            while (counum < 10)
            {
                ++counum;
                Thread.Sleep(1000);
                box.Items.Add(str+"--"+counum.ToString());
            }
            counum = 0;
            mu.ReleaseMutex();
        }
    }
}